home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / raytrace / rayshade / graphtal.lzh / Graphtal.Amiga / Production.C < prev    next >
C/C++ Source or Header  |  1992-11-19  |  3KB  |  105 lines

  1. /*
  2.  * Production.C - methods for L-System productions.
  3.  *
  4.  * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
  5.  *                     University of Berne, Switzerland
  6.  * All rights reserved.
  7.  *
  8.  * This software may be freely copied, modified, and redistributed
  9.  * provided that this copyright notice is preserved on all copies.
  10.  *
  11.  * You may not distribute this software, in whole or in part, as part of
  12.  * any commercial product without the express consent of the authors.
  13.  *
  14.  * There is no warranty or other guarantee of fitness of this software
  15.  * for any purpose.  It is provided solely "as is".
  16.  *
  17.  */
  18.  
  19. #include <stdlib.h>
  20. #include "Production.h"
  21. #include "Error.h"
  22.  
  23. implementList(ProductionList, ProductionPtr);
  24.  
  25. //___________________________________________________________ Production
  26.  
  27. Production::Production(Predecessor* p, Expression* c, SuccessorList* s)
  28. : _name(p->name), predecessor(p), condition(c), successors(s)
  29. {
  30.   arg_count = (p->formalParam) ? (int)p->formalParam->count()
  31.                                : 0;
  32.   stochastic = (successors->count() > 1);
  33. }
  34.  
  35. Production::~Production()
  36. {
  37.   delete  predecessor;
  38.   if (condition) delete condition;
  39.  
  40.   for (long i=0; i<successors->count(); i++)
  41.     delete successors->item(i);
  42.   delete successors;
  43. }
  44.  
  45. // choose a successor out of the successor list and clone it
  46. ModuleList* Production::cloneSuccessor()
  47. {
  48.   // if we have more than one successor, choose by random
  49.   if (stochastic) {
  50.     double p = drand48();
  51.     for (register long i=0; i<successors->count(); i++)
  52.       if (p <= successors->item(i)->probability())
  53.     return successors->item(i)->clone();
  54.  
  55.     // No successor choosen. VERY, VERY BAD!
  56.     Error(ERR_PANIC, "cloneSuccessor: no successor choosen");
  57.     return NULL;
  58.   }  
  59.   else
  60.     return successors->item(0)->clone();
  61. }
  62.  
  63. // The probabilities of the successor must cumulate to 1. In addition
  64. //  a preprocessing is done, e.g.:
  65. //    A -> (0.5) B    =>  A -> (0.5) B
  66. //      -> (0.5) C          -> (1.0) C
  67. //  => no arithmetic operation has to be performed will choosing a
  68. //     successor
  69. int Production::cumulateProbability()
  70. {
  71.   double sum = 0.0;
  72.  
  73.   for (long i=0; i<successors->count(); i++) {
  74.     sum += successors->item(i)->probability();
  75.     successors->item(i)->probability() = sum;
  76.   }
  77.   return ((sum > 1.01) ? 1 : 0);
  78. }
  79.  
  80. int Production::hashValue()
  81. {
  82.   extern unsigned int modHash(const char*, long);
  83.   return modHash((const char*)_name, (long)arg_count);
  84. }
  85.  
  86. ostream& operator<<(ostream& os, Production& p)
  87. {
  88.   long i;
  89.  
  90.   os << p.predecessor->name;
  91.   if (p.predecessor->formalParam) {
  92.     os << '(';
  93.     for (i=0; i<p.predecessor->formalParam->count()-1; i++)
  94.       os << *p.predecessor->formalParam->item(i) << ", ";
  95.     os << *p.predecessor->formalParam->item(i) << ")";
  96.   }
  97.   if (p.condition) os << " : " << *p.condition << ' ';
  98.  
  99.   for (i=0; i<p.successors->count()-1; i++)
  100.     os << *p.successors->item(i) << "\n\t";
  101.   os << *p.successors->item(i) << '\n';
  102.   
  103.   return os;
  104. }
  105.